package midend.IR_Instruction;

import midend.IR_Type.IR_Const;
import midend.IR_Type.IR_Int1;
import midend.IR_Type.IR_Int32;
import midend.IR_Type.IR_Type;
import midend.IR_Value.IR_BaseBlock;
import midend.IR_Value.IR_FuncBlock;
import midend.IR_Value.IR_Local_Value;
import midend.IR_Value.IR_Value;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Cond_Instruction extends Instruction{
    private int cond;
    public Cond_Instruction(List<IR_Value> op, IR_BaseBlock bb,int icmpTyppe) {
        super(op, bb);
        cond = icmpTyppe;
        addValue(get_op_index(1));
        addValue(get_op_index(2));
    }

    public void updateop(int index, IR_Value newValue) {
        if(index >= 0 && index <= 1){
            set_Op(index + 1, newValue);
        }
    }
    public int get_cond() {
        if(IR_Int32.IR_Int32() == get_op().get(1).get_Type() && IR_Int32.IR_Int32() == get_op().get(2).get_Type()){
            return cond;
        }
        else if(IR_Int1.IR_Int1() == get_op().get(1).get_Type() && IR_Int1.IR_Int1() == get_op().get(2).get_Type()){
            return cond;
        }
        else{
            return cond + 6;
        }
    }

    public String toString(){
        //(resRegister, lhs, rhs)  op
        StringBuilder s = new StringBuilder();
        String cmps = null;
        String[] slist = null;
        if(IR_Int32.IR_Int32() == get_op().get(1).get_Type() && IR_Int32.IR_Int32() == get_op().get(2).get_Type()){
            cmps = IR_Const.ICMP;
            slist = IR_Const.int_Compare;
        }
        else if(IR_Int1.IR_Int1() == get_op().get(1).get_Type() && IR_Int1.IR_Int1() == get_op().get(2).get_Type()){
            cmps = IR_Const.ICMP;
            slist = IR_Const.int_Compare;
        }
        else{
            cmps = IR_Const.FCMP;
            slist = IR_Const.float_Compare;
        }
        IR_Value lhs = get_op().get(1);
        s.append(get_op().get(0).get_ValueName()).append(" = ").append(cmps).append(" ")
                .append(slist[cond]).append(" ").append(get_op().get(1).get_Type().get_TypeName()).append(" ")
                .append(get_op().get(1).get_ValueName()).append(", ").append(get_op().get(2).get_ValueName());
        return s.toString();
    }


    @Override
    public Cond_Instruction clone(IR_BaseBlock block) {
        String copy_name = ((IR_Local_Value) get_op().get(0)).get_Local_Identity();
        IR_Type copy_type = get_op().get(0).get_Type();
        IR_Value res = new IR_Local_Value(copy_name, copy_type);
        ArrayList<IR_Value> copy_ops = new ArrayList<>();
        copy_ops.add(res);
        for (int i = 1 ; i< get_op().size() ; i++) {
            IR_Value copy_op  = get_op().get(i);
            if(IR_FuncBlock.cloneMap_Value.containsKey(copy_op)) {
                copy_op = IR_FuncBlock.cloneMap_Value.get(copy_op);
            }
            copy_ops.add(copy_op);
        }
        Cond_Instruction copy_ins = new Cond_Instruction(copy_ops, block, cond);
        return copy_ins;
    }
}
